﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Type;
using NHibernate.Transform;
using NHibernate.Cfg;

namespace HotelDAO.DAO
{
    /// <summary>
    /// Base DAO.
    /// </summary>
    /// <typeparam name="TE">The target entity type that this DAO will manipulate on</typeparam>
    /// <typeparam name="TK">The target entity key type</typeparam>
    public abstract class BaseDAO<TE, TK> : IBaseDAO<TE, TK>
    {
        #region Variables
        /// <summary>
        /// The entity name that th DAO manipulate on.
        /// </summary>
        protected string EntityName;

        /// <summary>
        /// Select all hql.
        /// </summary>
        protected string HqlSelectAll;

        /// <summary>
        /// Get count hql.
        /// </summary>
        protected string HqlCount;

        /// <summary>
        /// Delete by id hql.
        /// </summary>
        protected string HqlDelete;

        /// <summary>
        /// Delete all hql.
        /// </summary>
        protected string HqlDeleteAll;
        #endregion
        #region Properties
        

        /// <summary>
        /// Get stateless session.
        /// </summary>
        /// <returns></returns>
        protected abstract IStatelessSession GetStatelessSession();
        #endregion
        #region Constructors
        /// <summary>
        /// Initializes a new entityance of the <see cref="CommonDao{TE, TK}"/> class.
        /// The default entity name is the type short name.
        /// </summary>
        public BaseDAO()
            : this(typeof(TE).Name)
        {
        }

        /// <summary>
        /// Initializes a new entityance of the <see cref="CommonDao{TE, TK}"/> class.
        /// </summary>
        /// <param name="entityName">
        /// The entity name to pass on.
        /// </param>
        public BaseDAO(string entityName)
        {
            this.EntityName = entityName;
            this.InitHql();
        }
        #endregion
        #region Methods
        /// <summary>
        /// Initialize cached HQL statements.
        /// </summary>
        protected virtual void InitHql()
        {
            HqlCount = "select count(*) from " + EntityName + "%s";
            HqlDelete = "delete " + EntityName + " where id=?";
            HqlDeleteAll = "delete " + EntityName;
            HqlSelectAll = "from " + EntityName;
        }

        /// <summary>
        /// Get session.
        /// </summary>
        /// <returns></returns>
        public virtual ISession GetSession()
        {
            var config = new Configuration();
            return HotelDAOSessionFactory.OpenSession();
        }

        /// <summary>
        /// Set parameter for query.
        /// </summary>
        /// <param name="query"></param>
        /// <param name="values"></param>
        protected void SetParameters(IQuery query, params object[] values)
        {
            if (values != null)
            {
                for (int i = 0; i < values.Length; i++)
                {
                    query.SetParameter(i, values[i]);
                }
            }
        }

        /// <summary>
        /// Set parameter for query.
        /// </summary>
        /// <param name="query"></param>
        /// <param name="values"></param>
        protected void SetParameters(IQuery query, string[] names, object[] values)
        {
            if (names != null && values != null && names.Length == values.Length)
            {
                for (int i = 0; i < names.Length; i++)
                {
                    var name = names[i];
                    var value = values[i];
                    if (value is ICollection)
                    {
                        query.SetParameterList(name, value as ICollection);
                    }
                    else
                    {
                        query.SetParameter(name, value);
                    }
                }
            }
        }

        /// <summary>
        /// Add scalar for query.
        /// </summary>
        /// <param name="query"></param>
        /// <param name="columnAliases"></param>
        /// <param name="types"></param>
        protected void AddScalars(ISQLQuery query, string[] columnAliases, IType[] types)
        {
            if (columnAliases != null && types != null && columnAliases.Length == types.Length)
            {
                for (int i = 0; i < columnAliases.Length; i++)
                {
                    var columnAlias = columnAliases[i];
                    var type = types[i];
                    query.AddScalar(columnAlias, type);
                }
            }
        }



        /// <summary>
        /// Gets entity by the key.
        /// </summary>
        /// <param name="key">
        /// The specific key.
        /// </param>
        /// <returns>
        /// The matched entity.
        /// </returns>
        public virtual TE Get(TK key)
        {
            TE entity = default(TE);
            using (var session = this.GetSession())
            {
                entity = session.Get<TE>(key);
            }
            return entity;
        }

        /// <summary>
        /// Gets all entities
        /// </summary>
        /// <returns>The list of all entities</returns>
        public virtual IList<TE> GetAll()
        {
            IList<TE> entities = null;
            using (var session = this.GetSession())
            {
                entities = session.CreateQuery(this.HqlSelectAll).List<TE>();
            }
            return entities;
        }

        /// <summary>
        /// Save an entity to database.
        /// </summary>
        /// <param name="entity">
        /// The entity will be saved.
        /// </param>
        /// <returns>
        /// The key of the entity.
        /// </returns>
        public virtual TK Save(TE entity)
        {
            TK key = default(TK);
            using (var session = this.GetSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    key = (TK)session.Save(entity);
                    transaction.Commit();
                }
            }
            return key;
        }

        /// <summary>
        /// Save an entity to database.
        /// </summary>
        /// <param name="entity">
        /// The entity will be saved.
        /// </param>
        /// <returns>
        /// The key of the entity.
        /// </returns>
        public virtual void Save(IList<TE> entities)
        {           
            using (var session = this.GetSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    foreach (var entity in entities)
                    {
                        session.Save(entity);
                    }                    
                    transaction.Commit();
                }
            }            
        }

        /// <summary>
        /// Save or update an entity to database.
        /// </summary>
        /// <param name="entity">
        /// The entity will be saved/updated.
        /// </param>
        public void SaveOrUpdate(TE entity)
        {
            using (var session = this.GetSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    session.SaveOrUpdate(entity);
                    transaction.Commit();
                }
            }
        }

        /// <summary>
        /// Save or update a list of entities.
        /// </summary>
        /// <param name="entities">
        /// The entity list.
        /// </param>
        public void SaveOrUpdate(ICollection<TE> entities)
        {
            using (var session = this.GetSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    foreach (var entity in entities)
                    {
                        session.SaveOrUpdate(entity);
                    }
                    transaction.Commit();
                }
            }
        }

        /// <summary>
        /// Merge an entity to database.
        /// </summary>
        /// <param name="entity">
        /// The entity will be merge.
        /// </param>
        /// <returns>Entity object after merged</returns>
        public TE Merge(TE entity)
        {
            TE mergedEntity = default(TE);
            using (var session = this.GetSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    mergedEntity = (TE)session.Merge(entity);
                    transaction.Commit();
                }
            }
            return mergedEntity;
        }

        /// <summary>
        /// Merge a list of entities.
        /// </summary>
        /// <param name="entities">
        /// The entity list.
        /// </param>
        /// <returns>A list of entity object after merged</returns>
        public ICollection<TE> Merge(ICollection<TE> entities)
        {
            var mergedEntityList = new List<TE>();
            using (var session = this.GetSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    foreach (var entity in entities)
                    {
                        var mergedEntity = (TE)session.Merge(entity);
                        mergedEntityList.Add(mergedEntity);
                    }
                    transaction.Commit();
                }
            }
            return mergedEntityList;
        }


        /// <summary>
        /// Find a list of matched entities by providing an hql and its parameters.
        /// </summary>
        /// <param name="queryString">
        /// The hql query.
        /// </param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        public IList<TE> Find(string queryString, params object[] values)
        {
            IList<TE> list = null;
            using (var session = this.GetSession())
            {
                var query = session.CreateQuery(queryString);
                this.SetParameters(query, values);
                list = query.List<TE>();
            }
            return list;
        }

        /// <summary>
        /// Find by sql query
        /// </summary>
        /// <param name="sqlQuery"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public IList<TE> FindBySQLQuery(string sqlQuery, params object[] values)
        {
            IList<TE> list = null;
            using (var session = this.GetSession())
            {
                var query = session.CreateSQLQuery(sqlQuery);
                this.SetParameters(query, values);
                list = query.List<TE>();
            }
            return list;
        }

        /// <summary>
        /// Find by sql query
        /// </summary>
        /// <param name="sqlQuery"></param>
        /// <param name="names"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public IList<TC> FindBySQLQuery<TC>(string sqlQuery, string[] names, object[] values)
        {
            IList<TC> list = null;
            using (var session = this.GetSession())
            {
                var query = session.CreateSQLQuery(sqlQuery);
                this.SetParameters(query, names, values);
                list = query.List<TC>();
            }
            return list;
        }

        /// <summary>
        /// Find by sql query
        /// </summary>
        /// <param name="sqlQuery"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public IList<TC> FindBySQLQuery<TC>(string sqlQuery, params object[] values)
        {
            IList<TC> list = null;
            using (var session = this.GetSession())
            {
                var query = session.CreateSQLQuery(sqlQuery);
                this.SetParameters(query, values);
                list = query.List<TC>();
            }
            return list;
        }

        /// <summary>
        /// Find a list of entities by provide a named HQL and its parameters.
        /// </summary>
        /// <param name="queryName">
        /// The HQL query name.
        /// </param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        public IList<TE> FindByNamedQuery(string queryName, params object[] values)
        {
            IList<TE> list = null;
            using (var session = this.GetSession())
            {
                var query = session.GetNamedQuery(queryName);
                this.SetParameters(query, values);
                list = query.List<TE>();
            }
            return list;
        }

        /// <summary>
        /// Find a list of entities by provide a custom HQL and its parameters.
        /// </summary>
        /// <param name="queryString">
        /// The HQL query string.
        /// </param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        public IList<CT> FindCustomByHQLQuery<CT>(string queryString, params object[] values)
        {
            IList<CT> list = null;
            using (var session = this.GetSession())
            {
                var query = session.CreateQuery(queryString);
                this.SetParameters(query, values);
                list = query.List<CT>();
            }
            return list;
        }

        /// <summary>
        /// Find a list of entities by provide a custom HQL and its parameters.
        /// </summary>
        /// <param name="queryString">
        /// The HQL query string.
        /// </param>
        /// <param name="names"></param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        public IList<CT> FindCustomByHQLQuery<CT>(string queryString, string[] names, object[] values)
        {
            IList<CT> list = null;
            using (var session = this.GetSession())
            {
                var query = session.CreateQuery(queryString);
                this.SetParameters(query, names, values);
                list = query.List<CT>();
            }
            return list;
        }

        /// <summary>
        /// Find a list of entities by provide a named HQL and its parameters.
        /// </summary>
        /// <param name="queryName">
        /// The HQL query name.
        /// </param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        public IList<CT> FindCustomByNamedQuery<CT>(string queryName, params object[] values)
        {
            IList<CT> list = null;
            using (var session = this.GetSession())
            {
                var query = session.GetNamedQuery(queryName);
                this.SetParameters(query, values);
                list = query.List<CT>();
            }
            return list;
        }

        /// <summary>
        /// Find a list of entities by provide a named HQL and its parameters.
        /// </summary>
        /// <param name="queryName">
        /// The HQL query name.
        /// </param>
        /// <param name="names">
        /// The name of parameters
        /// </param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        public IList<CT> FindCustomByNamedQuery<CT>(string queryName, string[] names, object[] values)
        {
            IList<CT> list = null;
            using (var session = this.GetSession())
            {
                var query = session.GetNamedQuery(queryName);
                this.SetParameters(query, names, values);
                list = query.List<CT>();
            }
            return list;
        }

        /// <summary>
        /// Find a list of entities by provide a HQL, transfomer and its parameters.
        /// </summary>
        /// <param name="queryString">
        /// The HQL query name.
        /// </param>
        /// <param name="transformer">
        /// The result transformer
        /// </param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        protected IList<TC> FindByResultTransformer<TC>(string queryString, IResultTransformer transformer, params object[] values)
        {
            IList<TC> list = null;
            using (var session = this.GetSession())
            {
                var query = session.CreateQuery(queryString).SetResultTransformer(transformer);
                this.SetParameters(query, values);
                list = query.List<TC>();
            }
            return list;
        }

        /// <summary>
        /// Find by result transformer.
        /// </summary>
        /// <typeparam name="TC"></typeparam>
        /// <param name="queryString"></param>
        /// <param name="transformer"></param>
        /// <param name="names"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        protected IList<TC> FindByResultTransformer<TC>(string queryString, IResultTransformer transformer, string[] names, object[] values)
        {
            IList<TC> list = null;
            using (var session = this.GetSession())
            {
                var query = session.CreateQuery(queryString).SetResultTransformer(transformer);
                this.SetParameters(query, names, values);
                list = query.List<TC>();
            }
            return list;
        }

        /// <summary>
        /// Find a list of entities by provide a HQL, transfomer and its parameters.
        /// </summary>
        /// <param name="sqlQuery">
        /// The SQL query
        /// </param>
        /// <param name="transformer">
        /// The result transformer
        /// </param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        protected IList<TC> FindByResultTransformerSQLQuery<TC>(string sqlQuery, IResultTransformer transformer, params object[] values)
        {
            IList<TC> list = null;
            using (var session = this.GetSession())
            {
                var query = session.CreateSQLQuery(sqlQuery).SetResultTransformer(transformer);
                this.SetParameters(query, values);
                list = query.List<TC>();
            }
            return list;
        }

        /// <summary>
        /// Find by result transformer.
        /// </summary>
        /// <typeparam name="TC"></typeparam>
        /// <param name="sqlQuery"></param>
        /// <param name="transformer"></param>
        /// <param name="names"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        protected IList<TC> FindByResultTransformerSQLQuery<TC>(string sqlQuery, IResultTransformer transformer, string[] names, object[] values)
        {
            IList<TC> list = null;
            using (var session = this.GetSession())
            {
                var query = session.CreateSQLQuery(sqlQuery).SetResultTransformer(transformer);
                this.SetParameters(query, names, values);
                list = query.List<TC>();
            }
            return list;
        }

        /// <summary>
        /// Find by result transformer.
        /// </summary>
        /// <typeparam name="TC"></typeparam>
        /// <param name="sqlQuery"></param>
        /// <param name="transformer"></param>
        /// <param name="names"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        protected IList<TC> FindByResultTransformerSQLQuery<TC>(string sqlQuery, IResultTransformer transformer,
            string[] columnAliases, IType[] types,
            string[] names, object[] values)
        {
            IList<TC> list = null;
            using (var session = this.GetSession())
            {
                var query = session.CreateSQLQuery(sqlQuery);
                query.SetResultTransformer(transformer);
                this.AddScalars(query, columnAliases, types);
                this.SetParameters(query, names, values);
                list = query.List<TC>();
            }
            return list;
        }

        /// <summary>
        /// Find by result transformer.
        /// </summary>
        /// <typeparam name="TC"></typeparam>
        /// <param name="queryName"></param>
        /// <param name="transformer"></param>
        /// <param name="names"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        protected IList<TC> FindByResultTransformerNamedQuery<TC>(string queryName, IResultTransformer transformer, string[] names, object[] values)
        {
            IList<TC> list = null;
            using (var session = this.GetSession())
            {
                var query = session.GetNamedQuery(queryName).SetResultTransformer(transformer);
                this.SetParameters(query, names, values);
                list = query.List<TC>();
            }
            return list;
        }



        /// <summary>
        /// Find a list of entities by provide a named HQL, transfomer and its parameters.
        /// </summary>
        /// <param name="queryName">
        /// The HQL query name.
        /// </param>
        /// <param name="transformer">
        /// The result transformer
        /// </param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        protected IList<TC> FindByResultTransformerNamedQuery<TC>(string queryName, IResultTransformer transformer, params object[] values)
        {
            IList<TC> list = null;
            using (var session = this.GetSession())
            {
                var query = session.GetNamedQuery(queryName).SetResultTransformer(transformer);
                this.SetParameters(query, values);
                list = query.List<TC>();
            }
            return list;
        }

        /// <summary>
        /// Find the first matched entity by providing an HQL and its parameters.
        /// </summary>
        /// <param name="query">
        /// The HQL query.
        /// </param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entity or null if not found.
        /// </returns>
        public TE FindOne(string queryString, params object[] values)
        {
            TE entity = default(TE);
            using (var session = this.GetSession())
            {
                var query = session.CreateQuery(queryString);
                this.SetParameters(query, values);
                entity = query.UniqueResult<TE>();
            }
            return entity;
        }

        /// <summary>
        /// Find one by named query.
        /// </summary>
        /// <param name="queryName"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public TE FindOneByNamedQuery(string queryName, params object[] values)
        {
            TE entity = default(TE);
            using (var session = this.GetSession())
            {
                var query = session.GetNamedQuery(queryName);
                this.SetParameters(query, values);
                entity = query.UniqueResult<TE>();
            }
            return entity;
        }

        /// <summary>
        /// Find one by named query.
        /// </summary>
        /// <param name="queryName"></param>
        /// <param name="names"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public TE FindOneByNamedQuery(string queryName, string[] names, object[] values)
        {
            TE entity = default(TE);
            using (var session = this.GetSession())
            {
                var query = session.GetNamedQuery(queryName);
                this.SetParameters(query, names, values);
                entity = query.UniqueResult<TE>();
            }
            return entity;
        }

        /// <summary>
        /// Find one by named query.
        /// </summary>
        /// <typeparam name="TC"></typeparam>
        /// <param name="queryName"></param>
        /// <param name="names"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public TC FindCustomOneByNameQuery<TC>(string queryName, string[] names, object[] values)
        {
            TC entity = default(TC);
            using (var session = this.GetSession())
            {
                var query = session.GetNamedQuery(queryName);
                this.SetParameters(query, names, values);
                entity = query.UniqueResult<TC>();
            }
            return entity;
        }

        /// <summary>
        /// Get number of matched entities by providing an HQL query and 
        /// its parameter values.
        /// </summary>
        /// <param name="queryString">
        /// The HQL query.
        /// </param>
        /// <param name="values">
        /// The query parameter values.
        /// </param>
        /// <returns>
        /// The number of matched entities.
        /// </returns>
        public long GetCount(string queryString, params object[] values)
        {
            long count = 0;
            using (var session = this.GetSession())
            {
                var query = session.CreateQuery("select count(*) " + queryString);
                this.SetParameters(query, values);
                var obj = query.UniqueResult();
                if (obj != null)
                {
                    count = long.Parse(obj.ToString());
                }
            }
            return count;
        }

        /// <summary>
        /// Get SQL Count
        /// </summary>
        /// <param name="sqlString"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public long GetSqlCount(string sqlString, params object[] values)
        {
            long count = 0;
            using (var session = this.GetSession())
            {
                var sqlQuery = session.CreateSQLQuery("select count(*) " + sqlString);
                this.SetParameters(sqlQuery, values);
                var obj = sqlQuery.UniqueResult();
                if (obj != null)
                {
                    count = long.Parse(obj.ToString());
                }
            }
            return count;
        }

        /// <summary>
        /// Get max by named query.
        /// </summary>
        /// <param name="queryName"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public long GetMaxByNamedQuery(string queryName, params object[] values)
        {
            long max = 0;
            using (var session = this.GetSession())
            {
                var query = session.GetNamedQuery(queryName);
                this.SetParameters(query, values);
                var obj = query.UniqueResult();
                if (obj != null)
                {
                    max = long.Parse(obj.ToString());
                }
            }
            return max;
        }

        /// <summary>
        /// Get max by named query.
        /// </summary>
        /// <param name="queryName"></param>
        /// <param name="names"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public long GetMaxByNamedQuery(string queryName, string[] names, object[] values)
        {
            long max = 0;
            using (var session = this.GetSession())
            {
                var query = session.GetNamedQuery(queryName);
                this.SetParameters(query, names, values);
                var obj = query.UniqueResult();
                if (obj != null)
                {
                    max = long.Parse(obj.ToString());
                }
            }
            return max;
        }

        /// <summary>
        /// Delete an entity.
        /// </summary>
        /// <param name="entity">
        /// The entity to delete.
        /// </param>
        public void Delete(TE entity)
        {
            using (var session = this.GetSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    session.Delete(entity);
                    transaction.Commit();
                }
            }
        }

        /// <summary>
        /// Delete a list of entity.
        /// </summary>
        /// <param name="entities">
        /// The entities to delete.
        /// </param>
        public void DeleteAll(IList<TE> entities)
        {
            using (var session = this.GetSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    foreach (var entity in entities)
                    {
                        session.Delete(entity);
                    }
                    transaction.Commit();
                }
            }
        }

        /// <summary>
        /// Delete the entity by its key
        /// </summary>
        /// <param name="key">
        /// The entity key.
        /// </param>
        /// <returns>
        /// Number of affected entity ussual 
        /// </returns>
        public int DeleteByKey(TK key)
        {
            int count;
            using (var session = this.GetSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    var query = session.CreateQuery(this.HqlDelete);
                    query.SetParameter(0, key);
                    count = query.ExecuteUpdate();
                    transaction.Commit();
                }
            }
            return count;
        }

        /// <summary>
        /// Delete entities by their keys
        /// </summary>
        /// <param name="keys">
        /// The entity keys
        /// </param>
        public int DeleteByKeys(IList<TK> keys)
        {
            int count = 0;
            using (var session = this.GetSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    foreach (var key in keys)
                    {
                        var query = session.CreateQuery(this.HqlDelete);
                        query.SetParameter(0, key);
                        count += query.ExecuteUpdate();
                    }
                    transaction.Commit();
                }
            }
            return count;
        }

        /// <summary>
        /// Batch update entities by providing an HQL query and 
        /// its paramenter values
        /// </summary>
        /// <param name="queryString">
        /// The HQL query
        /// </param>
        /// <param name="paras">
        /// The query parameters
        /// </param>
        /// <returns>
        /// Number of affected entities
        /// </returns>
        public int BatchUpdate(string queryString, params object[] values)
        {
            int count;
            using (var session = this.GetSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    var query = session.CreateQuery(queryString);
                    this.SetParameters(query, values);
                    count = query.ExecuteUpdate();
                    transaction.Commit();
                }
            }
            return count;
        }

        /// <summary>
        /// Batch update entities by providing a named HQL query and
        /// its paramenter values
        /// </summary>
        /// <param name="queryName">
        /// The named HQL query
        /// </param>
        /// <param name="values">
        /// The query parameters
        /// </param>
        /// <returns>
        /// Number of affected entities
        /// </returns>
        public int BatchUpdateByNamedQuery(string queryName, params object[] values)
        {
            int count;
            using (var session = this.GetSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    var query = session.GetNamedQuery(queryName);
                    this.SetParameters(query, values);
                    count = query.ExecuteUpdate();
                    transaction.Commit();
                }
            }
            return count;
        }

        /// <summary>
        /// Batch stateless insert.
        /// </summary>
        /// <param name="entities">List of entities</param>
        public void BatchStatelessInsert(IList<TE> entities)
        {
            using (var statelessSession = this.GetStatelessSession())
            {
                using (var transaction = statelessSession.BeginTransaction())
                {
                    foreach (var entity in entities)
                    {
                        statelessSession.Insert(entity);
                    }
                    transaction.Commit();
                }
            }
        }

        /// <summary>
        /// Batch stateless update.
        /// </summary>
        /// <param name="entities">List of entites</param>
        public void BatchStatelessUpdate(IList<TE> entities)
        {
            using (var statelessSession = this.GetStatelessSession())
            {
                using (var transaction = statelessSession.BeginTransaction())
                {
                    foreach (var entity in entities)
                    {
                        statelessSession.Update(entity);
                    }
                    transaction.Commit();
                }
            }
        }
        #endregion
    }
}
